/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package shaman.storage.impl.stream.filter.block;

import java.io.IOException;
import java.io.OutputStream;

/**
 *
 * @autfhor dmitriy
 */
public class BlockFilterOutputStream extends OutputStream {

    private final BlockTransformer blkTrans;
    private final int blkSize;
    private final byte[] buffer;
    private final OutputStream out;

    private int bufferPos;

    public BlockFilterOutputStream(OutputStream baseStream, BlockTransformer blkTrans) {
        out=baseStream;
        this.blkTrans = blkTrans;
        blkSize=this.blkTrans.getBlockSize();
        buffer=new byte[blkSize];
    }

    @Override
    public void write(int b) throws IOException {
        buffer[bufferPos++]=(byte) b;
        if (bufferPos==buffer.length)
        {
            bufferPos=0;
            writeOut();
        }
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        int writtenLen=0;
        while (writtenLen<len)
        {
            writtenLen+=doWrite(b, off+writtenLen, len-writtenLen);
        }
    }

    private int doWrite(byte[] b, int off, int len) throws IOException {
        int availLen=(blkSize-bufferPos%blkSize);
        int realLen=Math.min(len, availLen);
        System.arraycopy(b, off, buffer, bufferPos, realLen);
        bufferPos+=realLen;
        if (bufferPos>=buffer.length)
        {
            bufferPos=0;
            writeOut();
        }
        return realLen;
    }

    private void writeOut() throws IOException {
        blkTrans.forward(buffer);
        out.write(buffer);
    }

    private void writeLast() throws IOException {
        int i;
        for (i=bufferPos; i<blkSize; i++)
            buffer[i]=0;
        writeOut();
    }

    @Override
    public void close() throws IOException {
        writeLast();
        super.close();
    }

}
